//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using OpenLS.Chart.UI.Internals;

namespace OpenLS.Chart.UI
{
    class AreaSeriesToPointsConverter : IMultiValueConverter
    {

        #region IMultiValueConverter Members

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            int i = 0;
            var s = (AreaSeries)values[i++];
            var chart = (AreaChart) values[i++];
            if (chart == null)
                return null;
            ChartLayout info = ChartToChartInfoConverter.GetInfo(chart);
            var width = (double)values[i++];
            var height = (double)values[i++];
            var min = (double)values[i++];
            var max = (double)values[i++];
            var orientation = (AxisOrientation)values[i++];
            var categoryOrientation = (AxisOrientation)values[i++];
            var result = new PointCollection();
            var numericValues = new List<NumericValue>(s.Values.NumericValues);
            var projector = new ValueAxisProjector(min, max, height, 0, orientation);
            bool previousNegative = false;
            const double cross = 0;
            double previousValue = cross;
            int previousIndex = 0;
            foreach (NumericValue numericValue in numericValues)
            {
                double x = CategoryAxisPanel.GetScreenPosition(numericValue.Index, 0, info.Count - 1, 0, width, categoryOrientation, true);
                Bounds b = info.GetBounds(numericValue, s, 0);
                double value = b.High;
                if (value == cross)
                    value = b.Low;
                bool negative = value <= cross;
                if (previousNegative != negative && previousValue != value && previousValue != cross && value != cross)
                {
                    double ii = previousIndex  + Math.Abs((previousValue - cross)/(previousValue - value) * ( numericValue.Index - previousIndex)) ;
                    double xx = CategoryAxisPanel.GetScreenPosition(ii, 0, info.Count - 1, 0, width, categoryOrientation,
                                                                    true);
                    result.Add(new Point(xx, projector.GetValue(cross)));
                }
                double y = projector.GetValue(info.GetValue(numericValue, s, 0));
                result.Add(new Point(x, y));
                previousValue = value;
                previousNegative = value <= cross;
                previousIndex = numericValue.Index;
            }
            previousValue = 0;
            previousIndex = 0;
            previousNegative = false;
            numericValues.Reverse();
            projector = new ValueAxisProjector(min, max, height, 0, orientation);
            foreach (NumericValue numericValue in numericValues)
            {
                double x = CategoryAxisPanel.GetScreenPosition(numericValue.Index, 0, info.Count - 1, 0, width, categoryOrientation, true);
                Bounds b = info.GetBounds(numericValue, s, 0);
                double value = b.Low;
                if (value == cross)
                    value = b.High;
                bool negative = value <= cross;
                if (previousNegative != negative && previousValue != value && previousValue != cross && value != cross)
                {
                    double ii = previousIndex - Math.Abs((previousValue - cross) / (previousValue - value) * (numericValue.Index - previousIndex));
                    double xx = CategoryAxisPanel.GetScreenPosition(ii, 0, info.Count - 1, 0, width, categoryOrientation,
                                                                    true);
                    result.Add(new Point(xx, projector.GetValue(cross)));
                }
                double y = projector.GetValue(b.Low);
                result.Add(new Point(x, y));
                previousValue = value;
                previousNegative = value <= cross;
                previousIndex = numericValue.Index;

                
            }
            return result;
        }
       /* static double GetVisualValue(double logicalMin, double logicalMax, double visualMin, double visualMax, double value)
        {

            logicalMin = Math.Min(logicalMin, 0);
            logicalMax = Math.Max(logicalMax, 0);
            if (logicalMax == logicalMin)
                return visualMin;
            return visualMin + (value - logicalMin) / (logicalMax - logicalMin) * (visualMax - visualMin);
        }*/

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        #endregion
    }
}
